package com.qx.chat.akka.actor;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.web.socket.WebSocketSession;

import com.qx.chat.akka.Qxchat;
import com.qx.chat.system.dao.AbstractRepository;
import com.qx.chat.system.dao.UserDaoImpl;
import com.qx.chat.system.entity.User;
import com.qx.chat.system.event.SessionEvent;
import com.qx.chat.system.event.SessionEvent.SessionAllOnlineMsg;
import com.qx.chat.system.event.SessionEvent.SessionClose;
import com.qx.chat.system.event.SessionEvent.SessionError;
import com.qx.chat.system.event.SessionEvent.SessionOpen;
import com.qx.chat.system.event.UserEvent;
import com.qx.chat.system.message.Data;
import com.qx.chat.system.util.SpringUtils;

import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.UntypedActor;

/**
 * 用户Actor管理类
 * 
 * @author cyf
 * 
 */
public class SessionActor extends UntypedActor {

    private static final Logger LOGGER = LoggerFactory.getLogger(SessionActor.class);
    
	public static final String ACTOR_ID = "session";

	private Map<String, ActorRef> users = new HashMap<>();

	@Override
	public void onReceive(Object message) throws Exception {
		// 有新的ws连接
		if (message instanceof SessionEvent.SessionOpen) {
			SessionOpen open = (SessionOpen) message;
			String loginName = open.getLoginName();
//			AbstractRepository<User> userDao = SpringUtils.getBean(UserDaoImpl.class);
//			userDao.getMongoTemplate().updateMulti(new Query(), new Update().unset("online"), User.class);
			WebSocketSession session = open.getSession();
			ActorRef userAc = users.get(loginName);
			// 存在则销毁
			if (userAc != null) {
				users.remove(loginName);
				Qxchat.getInstance().getAkkaSystem().stop(userAc);
			}
			userAc = getContext().actorOf(Props.create(UserActor.class, loginName,session), loginName);
			users.put(loginName, userAc);
			getContext().watch(userAc);
			//通知客户端登录
			userAc.tell(Data.buildEventMessage(new UserEvent.SessionOpen()), userAc);
			//广播消息
		} else if (message instanceof SessionEvent.SessionAllOnlineMsg) {
			SessionAllOnlineMsg msg = (SessionAllOnlineMsg) message;
			String loginName = msg.getLoginName();
			Data<?> data = msg.getData();
			for(Entry<String, ActorRef> entry:users.entrySet()){
				String key = entry.getKey();
				ActorRef userActor = entry.getValue();
				//过滤本人
				if(!key.equals(msg.getLoginName())&&key!=msg.getLoginName()){
					try {
				        // 通知对方
						userActor.tell(data, userActor);
					} catch (Exception e) {
						LOGGER.error("将"+loginName+"在线状态推送到"+key+"失败！");
					}
				}
	    	}
	        //连接异常
		} else if (message instanceof SessionEvent.SessionError) {
			SessionError open = (SessionError) message;
			String loginName = open.getLoginName();
			ActorRef userAc = users.get(loginName);
			// 存在则销毁
			if (userAc != null) {
				Qxchat.getInstance().getAkkaSystem().stop(userAc);
				users.remove(loginName);
			}
			//更新用户状态
			AbstractRepository<User> userDao = SpringUtils.getBean(UserDaoImpl.class);
			userDao.findAndModify("loginName",loginName, new Update().set("online", 0));
			//推送用户状态至全体在线
			User user = userDao.findOne("loginName",loginName);
    		UserEvent.Status st = new UserEvent.Status(user.getId(), user.getLoginName(), 0);
	        ActorRef sessionActor = Qxchat.getInstance().getSessionActor();
			sessionActor.tell(
					new SessionEvent.SessionAllOnlineMsg(loginName, Data.buildEventMessage(st)),
					sessionActor);
	        LOGGER.error("websocket connection exception: " + loginName);
	        //连接关闭
		} else if (message instanceof SessionEvent.SessionClose) {
			SessionClose open = (SessionClose) message;
			String loginName = open.getLoginName();
			ActorRef userAc = users.get(loginName);
			// 存在则销毁
			if (userAc != null) {
				Qxchat.getInstance().getAkkaSystem().stop(userAc);
				users.remove(loginName);
			}
			//更新用户状态
			AbstractRepository<User> userDao = SpringUtils.getBean(UserDaoImpl.class);
			userDao.findAndModify("loginName",loginName, new Update().set("online", 0));
			//推送用户状态至全体在线
			User user = userDao.findOne("loginName",loginName);
    		UserEvent.Status st = new UserEvent.Status(user.getId(), user.getLoginName(), 0);
	        ActorRef sessionActor = Qxchat.getInstance().getSessionActor();
			sessionActor.tell(
					new SessionEvent.SessionAllOnlineMsg(loginName, Data.buildEventMessage(st)),
					sessionActor);
	        LOGGER.error("websocket connection close: " + loginName);
		}

	}
}
